#include "front/text_normalize.h"

using namespace std;
using namespace ppspeech;

const wregex mcWregexLetterNumber(L"([A-Za-z]+[0-9]+)([A-Za-z0-9]*)");
const wregex mcWregexNumberLetter(L"([0-9]+([A-Za-z]+|Ω))([A-Za-z0-9]*)");

const map<string, string> MapStrStr_ZhMeasureUnitsTable = {
	//一、长度单位：
	{"km",  "千米"},
	{"m",	"米"},
	{"dm",	"分米"},
	{"cm",	"厘米"},
	{"mm",	"毫米"},
	{"um",	"微米"},		{"μm",	"微米"},
	{"nm",	"纳米"},
	{"ly",	"光年"},
//	{"au",	"天文单位"},	{"AU",	"天文单位"},
	{"in",	"英寸"},
	{"ft",	"英尺"},
	{"yd",	"码"},
	{"mi",	"英里"},
	{"nmi",	"海里"},
	{"fm",	"英寻"},
	{"fur",	"伏隆"},
	{"mil",	"密耳"},

	//二、面积单位：
	{"k㎡",		"平方千米"},	{"sq.km",	"平方千米"},
	{"㎡",		"平方米"},		{"sq.m",	"平方米"},
	{"d㎡",		"平方分米"},	{"sq.dm",	"平方分米"},
	{"c㎡",		"平方厘米"},	{"sq.cm",	"平方厘米"},
	{"m㎡",		"平方毫米"},	{"sq.mm",	"平方毫米"},
	{"ha",		"公顷"},
	{"acre",	"英亩"},
	{"sq.mi",	"平方英里"},
	{"sq.yd",	"平方码"},
	{"sq.ft",	"平方英尺"},
	{"sq.in",	"平方英寸"},
	{"sq.rd",	"平方竿"},

	//三、体积单位：
	{"km³",		"立方千米"},	{"cu.km",	"立方千米"},
	{"m³",		"立方米"},		{"cu.m",	"立方米"},
	{"dm³",		"立方分米"},	{"cu.dm",	"立方分米"},
	{"cm³",		"立方厘米"},	{"cu.cm",	"立方厘米"},
	{"mm³",		"立方毫米"},	{"cu.mm",	"立方毫米"},
	{"l",		"升"},
	{"dl",		"分升"},
	{"ml",		"毫升"},
	{"cl",		"厘升"},
	{"hl",		"公石"},
	{"cu.ft",	"立方英尺"},
	{"cu.in",	"立方英寸"},
	{"cu.yd",	"立方码"},
	{"uk.gal",	"英制加仑"},
	{"us.gal",	"美制加仑"},
	{"ul",		"微升"},		{"μl",		"微升"},
	{"oz",		"盎司"},		//英/美制液体盎司
	{"gal",		"加仑"},

	//四、质量单位：
	{"kg",	"千克"},
	{"g",	"克"},
	{"mg",	"毫克"},
	{"ug",	"微克"},	{"μg",	"微克"},
	{"t",	"吨"},
	{"q",	"公担"},
	{"lb",	"磅"},
	{"oz",	"盎司"},
	{"ct",	"克拉"},
	{"gr",	"格令"},
//	{"lt",	"长吨"},
//	{"st",	"短吨"},
//	{"st",	"英石"},
	{"dr",	"打兰"},

	//五、温度单位：
	{"℃",	"摄氏度"},	{"°C",	"摄氏度"},
	{"℉",	"华氏度"},	{"°F",	"华氏度"},
//	{"K",	"开氏度"},
	{"°Re",	"列氏度"},
	{"°R",	"兰氏度"},

	//六、压力单位：
	{"Pa",		"帕斯卡"},
	{"kPa",		"千帕"},		{"KPa",		"千帕"},
	{"hPa",		"百帕"},
	{"MPa",		"兆帕"},
	{"atm",		"标准大气压"},
	{"mmHg",	"毫米汞柱"},
	{"in.Hg",	"英寸汞柱"},
	{"bar",		"巴"},
	{"mbar",	"毫巴"},
	{"psf",		"磅力每平方英尺"},
	{"psi",		"磅力每平方英寸"},
	{"kg·f/c㎡","公斤力每平方厘米"},
	{"kg·f/㎡",	"公斤力每平方米"},

	//七、功率单位：
	{"W",		"瓦"},
	{"kW",		"千瓦"},		{"kw",		"千瓦"},
	{"hp",		"英制马力"},
	{"ps",		"米制马力"},
	{"kg·m/s",	"公斤·米每秒"},
	{"kcal/s",	"千卡每秒"},
	{"Btu/s",	"英热单位每秒"},
	{"ft·lb/s",	"英尺·磅每秒"},
	{"J/s",		"焦耳每秒"},
	{"N·m/s",	"牛顿·米每秒"},

	//八、热量单位：
	{"J",		"焦耳"},
	{"kg·m",	"公斤·米"},
	{"ps·h",	"米制马力·时"},
	{"hp·h",	"英制马力·时"},
	{"kW·h",	"千瓦·时"},
	{"cal",		"卡"},
	{"kcal",	"千卡"},
	{"btu",		"英热单位"},
	{"ft·lb",	"英尺·磅"},
	{"kJ",		"千焦"},

	//九、密度单位：
	{"kg/cm³",	"千克每立方厘米"},
	{"kg/dm³",	"千克每立方分米"},
	{"kg/m³",	"千克每立方米"},
	{"g/cm³",	"克每立方厘米"},
	{"g/dm³",	"克每立方分米"},
	{"g/m³",	"克每立方米"},

	//十、力学单位：
	{"N",	"牛"},
	{"kN",	"千牛"},
	{"kgf",	"千克力"},
	{"gf",	"克力"},
	{"tf",	"公吨力"},
	{"kip",	"千磅力"},
	{"dyn",	"达因"},

	//十一、时间单位：
//	{"yr",	"年"},
//	{"week","周"},
//	{"d",	"天"},
	{"h",	"时"},
	{"min",	"分"},
	{"s",	"秒"},
	{"ms",	"毫秒"},
	{"us",	"微秒"},	{"μs",	"微秒"},
	{"ns",	"纳秒"},

	//十二、速度单位：
	{"m/s",		"米每秒"},
	{"km/s",	"千米每秒"},
	{"km/h",	"千米每时"},
//	{"c",		"光速"},
	{"mach",	"马赫"},
	{"mile/h",	"英里每时"},
	{"in/s",	"英寸每秒"},

	//十三、存储单位：
	{"bit",	"比特"},
//	{"B",	"字节"},
	{"kB",	"千字节"},
	{"MB",	"兆字节"},
	{"GB",	"吉字节"},
	{"TB",	"太字节"},
	{"PB",	"拍字节"},
	{"EB",	"艾字节"},

//	{"k",	"千"},
//	{"M",	"兆"},
	{"G",	" G "},
//	{"T",	"太"},
//	{"P",	"拍"},
//	{"E",	"艾"},

	//十四、角度单位：
	{"°",		"度"},
	{"′",		"分"},
	{"rad",		"弧度"},
	{"mrad",	"毫弧度"},

	//十五、电流单位：
//	{"A",	"安培"},
	{"mA",	"毫安"},
	{"uA",	"微安"},	{"μA",	"微安"},

	//十六、电压单位：
	{"V",	"伏特"},	{"v",	"伏特"},
	{"mV",	"毫伏"},
	{"uV",	"微伏"},	{"μV",	"微伏"},

	//十七、电阻单位：
	{"Ω",	"欧姆"},
	{"mΩ",	"毫欧姆"},
	{"uΩ",	"微欧姆"},	{"μΩ",	"微欧姆"},

	//十八、电容单位：
//	{"F",	"法拉"},
	{"mF",	"毫法"},
	{"uF",	"微法"},	{"μF",	"微法"},
	{"nF",	"纳法"},
	{"pF",	"皮法"},

	//十九、物质的量：
	{"mol",	"摩尔"},

	//二十、光照强度：
	{"cd",	"坎德拉"},

	//二十一、频率单位：
	{"Hz",	"赫兹"},
	{"kHz",	"千赫兹"},
	{"MHz",	"兆赫兹"},
	{"GHz",	"吉赫兹"},

	//其他
	{"MT", "公吨"},
	{"Wh",	"瓦时"},
	{"L",	"升"},
	{"rpm",	"转每分钟"},
};

const map<string, string> MapStrStr_EnMeasureUnitsTable = {

	//零、英语序数词：
	{"st", "[ord]"},
	{"nd", "[ord]"},
	{"rd", "[ord]"},
	{"th", "[ord]"},

	//一、长度单位：
	{"km",  "kilometer"},
	{"m",	"meter"},
	{"dm",	"decimeter"},
	{"cm",	"centimeter"},
	{"mm",	"millimeter"},
	{"um",	"micrometer"},		{"μm",	"micrometer"},
	{"nm",	"nanometer"},
	{"ly",	"light year"},
//	{"au",	"astronomical unit"},	{"AU",	"astronomical unit"},
	{"in",	"inch"},
	{"ft",	"foot"},
	{"yd",	"yard"},
	{"mi",	"mile"},
	{"nmi",	"nautical mile"},
	{"fm",	"fathom"},
	{"fur",	"furlong"},
	//{"mil",	"mil"},

	//二、面积单位：
	{"k㎡",		"square kilometer"},	{"sq.km",	"square kilometer"},
	{"㎡",		"square meter"},		{"sq.m",	"square meter"},
	{"d㎡",		"square decimeter"},	{"sq.dm",	"square decimeter"},
	{"c㎡",		"square centimeter"},	{"sq.cm",	"square centimeter"},
	{"m㎡",		"square millimeter"},	{"sq.mm",	"square millimeter"},
	{"ha",		"hectare"},
	//{"acre",	"acre"},
	{"sq.mi",	"square mile"},
	{"sq.yd",	"square yard"},
	{"sq.ft",	"square foot"},
	{"sq.in",	"square inch"},
	{"sq.rd",	"square rod"},

	//三、体积单位：
	{"km³",		"cubic kilometer"},		{"cu.km",	"cubic kilometer"},
	{"m³",		"cubic meter"},			{"cu.m",	"cubic meter"},
	{"dm³",		"cubic decimeter"},		{"cu.dm",	"cubic decimeter"},
	{"cm³",		"cubic centimeter"},	{"cu.cm",	"cubic centimeter"},
	{"mm³",		"cubic millimeter"},	{"cu.mm",	"cubic millimeter"},
	{"l",		"liter"},
	{"dl",		"deciliter"},
	{"ml",		"milliliter"},
	{"cl",		"centi liter"},
	{"hl",		"hecto liter"},
	{"cu.ft",	"cubic foot"},
	{"cu.in",	"cubic inch"},
	{"cu.yd",	"cubic yard"},
	{"uk.gal",	"united kingdom gallon"},
	{"us.gal",	"united states gallon"},
	{"ul",		"microliter"},		{"μl",		"microliter"},
	{"oz",		"ounce"},		//英/美制液体盎司
	{"gal",		"gallon"},

	//四、质量单位：
	{"kg",	"kilogram"},
	{"g",	"gram"},
	{"mg",	"milligram"},
	{"ug",	"microgram"},	{"μg",	"microgram"},
	{"t",	"ton"},
	{"q",	"kintal"},
	{"lb",	"pound"},
	{"oz",	"ounce"},
	{"ct",	"carat"},
	{"gr",	"grain"},
//	{"lt",	"long ton"},
//	{"st",	"short ton"},
//	{"st",	"stone"},
	{"dr",	"dram"},

	//五、温度单位：
	{"℃",	"degree celsius"},		{"°C",	"degree celsius"},
	{"℉",	"degree fahrenheit"},	{"°F",	"degree fahrenheit"},
//	{"K",	"kelvin"},
	{"°Re",	"degree reaumur"},
	{"°R",	"degree rankine"},

	//六、压力单位：
	{"Pa",		"pascal"},
	{"kPa",		"kilo pascal"},		{"KPa",		"kilo pascal"},
	{"hPa",		"hecto pascal"},
	{"MPa",		"mega pascal"},
	{"atm",		"atmospheric"},
	{"mmHg",	"millimeter of mercury"},
	{"in.Hg",	"inch of mercury"},
//	{"bar",		"bar"},
	{"mbar",	"millibar"},
	{"psf",		"pounds per square foot"},
	{"psi",		"pounds per square inch"},
	{"kg·f/c㎡","kilogram force per square centimeter"},
	{"kg·f/㎡",	"kilogram force per square meter"},

	//七、功率单位：
	{"W",		"watt"},
	{"kW",		"kilowatt"},		{"kw",		"kilowatt"},
	{"hp",		"horsepower"},
	{"ps",		"pferdestarke"},
	{"kg·m/s",	"kilogram meter per second"},
	{"kcal/s",	"kilo calorie per second"},
	{"Btu/s",	"british thermal unit per second"},
	{"ft·lb/s",	"foot pound per second"},
	{"J/s",		"joule per second"},
	{"N·m/s",	"newton meter per second"},

	//八、热量单位：
	{"J",		"joule"},
	{"kg·m",	"kilogram meter"},
	{"ps·h",	"pferdestarke hour"},
	{"hp·h",	"horsepower hour"},
	{"kW·h",	"kilowatt hour"},
	{"cal",		"calorie"},
	{"kcal",	"kilo calorie"},
	{"btu",		"british thermal unit"},
	{"ft·lb",	"foot pound"},
	{"kJ",		"kilo joule"},

	//九、密度单位：
	{"kg/cm³",	"kilogram per cubic centimeter"},
	{"kg/dm³",	"kilogram per cubic decimeter"},
	{"kg/m³",	"kilogram per cubic meter"},
	{"g/cm³",	"gram per cubic centimeter"},
	{"g/dm³",	"gram per cubic decimeter"},
	{"g/m³",	"gram per cubic meter"},

	//十、力学单位：
	{"N",	"newton"},
	{"kN",	"kilo newton"},
	{"kgf",	"kilogram force"},
	{"gf",	"gram force"},
	{"tf",	"ton force"},
	{"kip",	"kilo pound"},
	{"dyn",	"dyne"},

	//十一、时间单位：
//	{"yr",	"year"},
//	{"week","week"},
//	{"d",	"day"},
	{"h",	"hour"},
	{"min",	"minute"},
	{"s",	"second"},
	{"ms",	"millisecond"},
	{"us",	"micro second"},	{"μs",	"micro second"},
	{"ns",	"nanosecond"},

	//十二、速度单位：
	{"m/s",		"meter per second"},
	{"km/s",	"kilometer per second"},
	{"km/h",	"kilometer per hour"},
//	{"c",		"light speed"},
//	{"mach",	"mach"},
	{"mile/h",	"mile per hour"},
	{"in/s",	"inch per second"},

	//十三、存储单位：
	{"bit",	"bit"},
	{"B",	"byte"},
	{"kB",	"kilobyte"},
	{"MB",	"megabyte"},
	{"GB",	"gigabyte"},
	{"TB",	"terabyte"},
	{"PB",	"petabyte"},
	{"EB",	"exabyte"},

//	{"k",	" K"},
//	{"M",	" M"},
	{"G",	" G "},
//	{"T",	" T"},
//	{"P",	" P"},
//	{"E",	" E"},

	//十四、角度单位：
	{"°",		"degree"},
	{"′",		"minute"},
	{"rad",		"radian"},
	{"mrad",	"milli radian"},

	//十五、电流单位：
	{"A",	"ampere"},
	{"mA",	"milli ampere"},
	{"uA",	"micro ampere"},	{"μA",	"micro ampere"},

	//十六、电压单位：
	{"V",	"volt"},			{"v",	"volt"},
	{"mV",	"milli volt"},
	{"uV",	"micro volt"},		{"μV",	"micro volt"},

	//十七、电阻单位：
	{"Ω",	"ohm"},
	{"mΩ",	"milli ohm"},
	{"uΩ",	"micro ohm"},		{"μΩ",	"micro ohm"},

	//十八、电容单位：
//	{"F",	"farad"},
	{"mF",	"milli farad"},
	{"uF",	"micro farad"},		{"μF",	"micro farad"},
	{"nF",	"nano farad"},
	{"pF",	"pico farad"},

	//十九、物质的量：
	{"mol",	"mole"},

	//二十、光照强度：
	{"cd",	"candela"},

	//二十一、频率单位：
	{"Hz",	"hertz"},
	{"kHz",	"kilo hertz"},
	{"MHz",	"mega hertz"},
	{"GHz",	"giga hertz"},

	//其他：
	{"MT", "metric ton"},
	{"Wh",	"watt hour"},
	{"L",	"liter"},
	{"rpm",	"revolutions per minute"},
};

//测试：
//1km,2m,3dm,4cm,5mm,6μm,7nm,8ly,9au,10in,11ft,12yd,13mi,14nmi,15fm,16fur,17mil,18um
//1k㎡,2㎡,3d㎡,4c㎡,5m㎡,6ha,7acre,8sq.mi,9sq.yd,10sq.ft,11sq.in,12sq.rd,13km²,14m²,15dm²,16cm²,17mm²,18km2,19m2,20dm2,21cm2,22mm2,23sq.km,24sq.m,25sq.dm,26sq.cm,27sq.mm
//1km³,2m³,3dm³,4cm³,5mm³,6l,7dl,8ml,9cl,10hl,11cu.ft,12cu.in,13cu.yd,14uk.gal,15us.gal,16ul,17oz,18gal,19km3,20m3,21dm3,22cm3,23mm3,24cu.km,25cu.m,26cu.dm,27cu.cm,28cu.mm
//1kg,2g,3mg,4μg,5t,6q,7lb,8oz,9ct,10gr,11lt,12st,13st,14dr,15ug,  1℃,2℉,3k,4°re,5°r,6°c,7°f

//1pa,2kpa,3hpa,4mpa,5atm,6mmhg,7in.hg,8bar,9mbar,10psf,11psi,12kg·f/c㎡,13kg·f/㎡,14kg·f/cm²,15kg·f/m²,16kg·f/cm2,17kg·f/m2
//1w,2kw,3hp,4ps,5kg·m/s,6kcal/s,7btu/s,8ft·lb/s,9j/s,10n·m/s,  1j,2kg·m,3ps·h,4hp·h,5kw·h,6cal,7kcal,8btu,9ft·lb,10kj
//1kg/cm³,2kg/dm³,3kg/m³,4g/cm³,5g/dm³,6g/m³,7kg/cm3,8kg/dm3,9kg/m3,10g/cm3,11g/dm3,12g/m3

//1n,2kn,3kgf,4gf,5tf,6kip,7dyn, 1yr,2week,3d,4h,5min,6s,7ms,8μs,9ns,10us
//1m/s,2km/s,3km/h,4c,5mach,6mile/h,7in/s, 1bit,2b,3kb,4mb,5gb,6tb,7pb,8eb
//1°,2′,3rad,4mrad, 1a,2ma,3μa,4ua, 1v,2mv,3μv,4uv, 1Ω,2mΩ,3μΩ,4uΩ,  1f,2mf,3μf,4nf,5pf,6uf, 7mol, 8cd,  1Hz,2kHz,3MHz,4GHz


// A608 -> A六零八
void TextNormalizer::TnReLetterNumber(wstring* fpInWsentence, const LanguageEnum fcInLanguage)
{
	wsmatch tWsmatch;

	while(regex_search(*fpInWsentence, tWsmatch, mcWregexLetterNumber))
	{
		string tStrReplace = "";
		string tStrLetterNumber = wstring2utf8string(tWsmatch[0]);	//匹配到横杆的字符串

		//判断匹配字符串前面是否有数字，数+英+数
		size_t tWsmatchPos = tWsmatch.position(0);
		if(tWsmatchPos > 0) {
			wstring tWstrNumber = L"";
			for(size_t i=1; i<=tWsmatchPos; i++) {
				const wchar_t tcWchar = (*fpInWsentence).at(tWsmatchPos-i);	//向前追溯字符串中的数字
				if( IsWcharNumber(tcWchar) == false ) {
					break;
				}
				tWstrNumber = tcWchar + tWstrNumber;
			}

			if(tWstrNumber != L"") {	//说明是"数+英+数"组合
				wstring tStrNumberLetter = tWstrNumber + wstring( tWsmatch[0] );
				TnReNumberLetter(&tStrNumberLetter, false, fcInLanguage);
				WstrReplacePosition(fpInWsentence, tWsmatch.position(0)-tWstrNumber.length(), tWsmatch.length(0)+tWstrNumber.length(), tStrNumberLetter);
				tStrReplace = wstring2utf8string(*fpInWsentence);
				continue;
			}
		}

		//----------------------------------
		vector<string> tItemLetNum;	//英+数+英+数+……
		string tPart = "";
		bool tLetter1Number0 = true;
		for(const char tChar : tStrLetterNumber) {
			if(tChar >= '0' && tChar <= '9') {
				if(tLetter1Number0 == true) {
					tItemLetNum.push_back(tPart);
					tPart = "";
				}
				tLetter1Number0 = false;
			}
			else {
				if(tLetter1Number0 == false) {
					tItemLetNum.push_back(tPart);
					tPart = "";
				}
				tLetter1Number0 = true;
			}
			tPart += tChar;
		}
		tItemLetNum.push_back(tPart);

		//---------------------
		size_t tPartSize = tItemLetNum.size();
		if(tPartSize > 2) {			//英+数+……，可以看作是车牌号或者密码组合
			tStrReplace = ReplaceMethod(tItemLetNum, (fcInLanguage==LANG_EN ? RME_en_letter_number : RME_zh_letter_number));
		}
		else if(tPartSize == 2) {	//英+数，拆分
			string tLetters = tItemLetNum[0];
			string tNumbers = tItemLetNum[1];
			transform(tLetters.begin(), tLetters.end(), tLetters.begin(), ::toupper);

			if(VecStr_NotSplitUpperWord.end() != std::find(VecStr_NotSplitUpperWord.begin(), VecStr_NotSplitUpperWord.end(), tLetters)) {
				//类似TOP10,CCTV10,英文部分转小写，数字部分按整数读。
				transform(tLetters.begin(), tLetters.end(), tLetters.begin(), ::tolower);		//大写转小写
				tStrReplace = " " + tLetters + " ";
				if(fcInLanguage==LANG_EN) {
					tStrReplace += ReplaceMethod(vector<string>{tNumbers}, RME_en_negative_decimal);
				}
				else {
					if(tNumbers == "1") {
						tStrReplace += "壹";
					}
					else {
						tStrReplace += ReplaceMethod(vector<string>{tNumbers}, RME_zh_negative_decimal);
					}
				}
				tStrReplace += " ";
			}
			else {
				//其他情况，类似于ABC123，按字符读。
				tStrReplace += ReplaceMethod(tItemLetNum, (fcInLanguage==LANG_EN ? RME_en_letter_number : RME_zh_letter_number)) + " ";
			}
		}

		WstrReplacePosition(fpInWsentence, tWsmatch.position(0), tWsmatch.length(0), utf8string2wstring(tStrReplace));
	}
}

// 16kHz -> 十六千赫兹
// 16G -> 十六G
// 608A -> 六零八A
void TextNormalizer::TnReNumberLetter(wstring* fpInWsentence, const bool fcInAppendFlag, const LanguageEnum fcInLanguage)
{
	wsmatch tWsmatch;
	while(regex_search(*fpInWsentence, tWsmatch, mcWregexNumberLetter))
	{
		const wstring tcInWstr = (*fpInWsentence);

		string tStrReplace = "";
		const string tStrMatch = wstring2utf8string(tWsmatch[0]);	//匹配到的字符串
		size_t tPosMatch = tWsmatch.position(0);
		size_t tLenMatch = tWsmatch.length(0);
		wstring tWstrAppendNegative = L"";
		wstring tWstrAppendDecimal = L"";
		wstring tWstrAppendUnit = L"";

		if(fcInAppendFlag) {
			if((tPosMatch - 1 > 0)  &&  tcInWstr.at(tPosMatch-1) == L'.') {
				for(size_t i=2; i<tPosMatch; i++) {
					const wchar_t tcWchar = tcInWstr.at(tPosMatch-i);
					if(IsWcharNumber( tcWchar ) == false) {
						break;
					}

					tWstrAppendDecimal = tcWchar + tWstrAppendDecimal;
				}

				tPosMatch -= tWstrAppendDecimal.length() + 1;	//调整匹配位置
				tLenMatch += tWstrAppendDecimal.length() + 1;
			}

			if((tPosMatch - 1 > 0)  &&  tcInWstr.at(tPosMatch-1) == L'-') {
				tWstrAppendNegative = L"-";
				tPosMatch -= tWstrAppendNegative.length();	//调整匹配位置
				tLenMatch += tWstrAppendNegative.length();
			}

			if((tPosMatch + tLenMatch < tcInWstr.length())  &&  tcInWstr.at(tPosMatch + tLenMatch) == L'/') {
				tWstrAppendUnit += L"/";
				for(size_t i=tPosMatch+tLenMatch+1; i<tcInWstr.length(); i++) {
					const wchar_t tcWchar = tcInWstr.at(i);
					if( IsWcharEnLetter(tcWchar) == false ) {
						break;
					}
					tWstrAppendUnit += tcWchar;
				}

				tLenMatch += tWstrAppendUnit.length();	//调整匹配位置
			}
		}

		//----------------------------------
		vector<string> tItemNumLet;	//数+英+数+……
		string tPart = "";
		bool tLetter1Number0 = false;
		for(const char tChar : tStrMatch) {
			if(tChar >= '0' && tChar <= '9') {
				if(tLetter1Number0 == true) {
					tItemNumLet.push_back(tPart);
					tPart = "";
				}
				tLetter1Number0 = false;
			}
			else {
				if(tLetter1Number0 == false) {
					tItemNumLet.push_back(tPart);
					tPart = "";
				}
				tLetter1Number0 = true;
			}
			tPart += tChar;
		}
		tItemNumLet.push_back(tPart);

		//---------------------
		size_t tPartSize = tItemNumLet.size();
		if(tPartSize > 2) {			//数+英+数+……，可以看作是车牌号或者密码组合
			tStrReplace = ReplaceMethod(tItemNumLet, (fcInLanguage==LANG_EN ? RME_en_letter_number : RME_zh_letter_number));
		}
		else if(tPartSize == 2) {
			const map<string, string>* tpMeasureUnitsTable = (fcInLanguage==LANG_EN)? (&MapStrStr_EnMeasureUnitsTable) : (&MapStrStr_ZhMeasureUnitsTable);
			string tNumbers = tItemNumLet[0];
			string tLetters = tItemNumLet[1];

			if(tWstrAppendUnit != L"") {
				tLetters += wstring2utf8string( tWstrAppendUnit );
			}

			const auto tFindMeasureUnit = tpMeasureUnitsTable->find(tLetters);
			if(tpMeasureUnitsTable->end() != tFindMeasureUnit) {
				string tStrNegDec = "";

				if(tWstrAppendNegative == L"-") {
					tStrNegDec += "-";
				}

				if(tWstrAppendDecimal == L"") {
					tStrNegDec += tNumbers;
				}
				else {
					tStrNegDec += wstring2utf8string( tWstrAppendDecimal );
					tStrNegDec += ".";
					tStrNegDec += tNumbers;
				}

				//类似16kHz、256G，数字部分按整数读，英文部分按单位读。
				transform(tLetters.begin(), tLetters.end(), tLetters.begin(), ::tolower);		//大写转小写
				tStrReplace += " ";

				//英语序数词
				if(fcInLanguage==LANG_EN) {
					if(tFindMeasureUnit->second == "[ord]") {
						const int tNum = stoi(tNumbers);
						if( (tNum >= 4 && tLetters == "th") || (tNum == 3 && tLetters == "rd") || (tNum == 2 && tLetters == "nd") || (tNum == 1 && tLetters == "st") ) {
							tStrReplace += ReplaceMethod(vector<string>{tNumbers}, RME_en_ordinal_number);
						}
						else {
							tStrReplace += tNumbers + " " + tLetters;
						}
					}
					else {
						tStrReplace += ReplaceMethod(vector<string>{tStrNegDec}, RME_en_negative_decimal);
						tStrReplace += " ";
						tStrReplace += tFindMeasureUnit->second;
					}
				}
				else {
					tStrReplace += ReplaceMethod(vector<string>{tStrNegDec}, RME_zh_negative_decimal);
					tStrReplace += tFindMeasureUnit->second;
				}
				tStrReplace += " ";
			}
			else {
				//其他情况，类似于608A，按字符读。
				tStrReplace += ReplaceMethod(tItemNumLet, (fcInLanguage==LANG_EN ? RME_en_letter_number : RME_zh_letter_number));
			}
		}

		WstrReplacePosition(fpInWsentence, tPosMatch, tLenMatch, utf8string2wstring(tStrReplace));
	}
}



const wregex mcWregexDecimalLetter(L"(\\d+\\.\\d+)[a-zA-Z]+");

void TextNormalizer::TnReDecimalLetter(wstring* fpInWsentence, const LanguageEnum fcInLanguage)
{
	wsmatch tWsmatch;

	while(regex_search(*fpInWsentence, tWsmatch, mcWregexDecimalLetter))
	{
		string tStrReplace = "";
		string tStrDecimalLetter = wstring2utf8string(tWsmatch[0]);	//匹配到小数字母的字符串

		string tStrNumber = "";
		string tStrLetter = "";
		for(const char tcChar : tStrDecimalLetter) {
			if(IsCharEnLetter(tcChar)) {
				tStrLetter += tcChar;
			}
			else if(IsCharNumber(tcChar) | tcChar == '.') {
				tStrNumber += tcChar;
			}
		}

		tStrReplace += ReplaceMethod(vector<string>{tStrNumber}, (fcInLanguage==LANG_EN?RME_en_negative_decimal:RME_zh_negative_decimal));
		tStrReplace += " ";
		tStrReplace += tStrLetter;

		WstrReplacePosition(fpInWsentence, tWsmatch.position(0), tWsmatch.length(0), utf8string2wstring(tStrReplace));
	}
}

